package cn.satoken.service.impl;

import cn.dev33.satoken.util.SaResult;
import cn.satoken.entity.CrmFile;
import cn.satoken.entity.config.MinioProperties;
import cn.satoken.mapper.FileMapper;
import io.minio.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.UUID;

import static cn.satoken.constant.FileConstant.*;

/**
 * <h3>saToken</h3>
 * <p>文件上传</p>
 *
 * @author gdw
 * @since 2025-05-28 15:49:25
 */
@Service
@RequiredArgsConstructor
public class MinioService {

    private final MinioClient minioClient;
    private final MinioProperties minioProperties;
    private final FileMapper fileMapper;

    //文件上传
    public SaResult uploadFile(MultipartFile file) throws Exception {
        // 原始文件名 + 后缀
        String originalFileName = file.getOriginalFilename();
        String extension = Optional.ofNullable(originalFileName)
                .filter(f -> f.contains("."))
                .map(f -> f.substring(f.lastIndexOf(".") + 1))
                .orElse("")
                .toLowerCase();

        // 生成唯一文件名
        String fileName = UUID.randomUUID() + "_" + originalFileName;

        // 根据扩展名选择桶
        String bucketName;
        switch (extension) {
            case FILE_SUFFIX_JPG:
            case FILE_SUFFIX_JPEG:
            case FILE_SUFFIX_PNG:
            case FILE_SUFFIX_GIF:
                bucketName =BUCKET_NAME_IMAGES;
                break;
            case FILE_SUFFIX_DOC:
            case FILE_SUFFIX_DOCX:
                bucketName = BUCKET_NAME_WORD;
                break;
            case FILE_SUFFIX_PDF:
                bucketName = BUCKET_NAME_PDF;
                break;
            default:
                bucketName = BUCKET_NAME_OTHERS;  // 不识别的后缀放到 others 桶
        }

        // 确保 bucket 存在
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }

        // 上传文件
        try (InputStream inputStream = file.getInputStream()) {
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .stream(inputStream, file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()
            );
        }
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
        String fullUrl = minioProperties.getEndpoint() + "/" + bucketName + "/" + encodedFileName;
        if(bucketName.equals(BUCKET_NAME_IMAGES)){
            return SaResult.data(fullUrl);
        }else{
            //保存文件信息
            CrmFile build = CrmFile.builder().name(originalFileName).url(fullUrl).build();
            fileMapper.insert(build);
            return SaResult.data(build);
        }
    }

    // 下载文件
    public InputStream downloadFile(String url) throws Exception {
        // 解析真实路径，去除前缀
        String path;
        if (url.startsWith("http://") || url.startsWith("https://")) {
            // 取出域名后的部分
            path = url.substring(url.indexOf("/", 10) + 1);  // 10 跳过 http:// 或 https:// 开头
        } else {
            path = url;
        }

        // 解码 URL 编码（防止中文名被转义）
        path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());

        // 拆分 bucket 和 object 名
        String[] parts = path.split("/", 2);
        if (parts.length != 2) {
            throw new IllegalArgumentException("无效的文件路径：" + path);
        }

        String bucket = parts[0];
        String object = parts[1];

        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucket)
                        .object(object)
                        .build()
        );
    }

    // 删除文件
    public void deleteFile(String url) throws Exception {
        // 解析真实路径，去除前缀
        String path;
        if (url.startsWith("http://") || url.startsWith("https://")) {
            // 取出域名后的部分
            path = url.substring(url.indexOf("/", 10) + 1);  // 10 跳过 http:// 或 https:// 开头
        } else {
            path = url;
        }

        // 解码 URL 编码（防止中文名被转义）
        path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());

        // 拆分 bucket 和 object 名
        String[] parts = path.split("/", 2);
        if (parts.length != 2) {
            throw new IllegalArgumentException("无效的文件路径：" + path);
        }

        String bucket = parts[0];
        String object = parts[1];

        // 调用 MinIO 删除接口
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucket)
                        .object(object)
                        .build()
        );
    }
}
